home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / programming / assemblers / cas.lha / op.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-14  |  8.5 KB  |  212 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "io.h"
  5. #include "ex.h"
  6. #include "st.h"
  7. #include "res.h"
  8. #include "op.h"
  9.  
  10. #define ELEMENTS(Arr) (sizeof(Arr)/sizeof(Arr[0]))
  11.  
  12. /* Translate controls:
  13.    X: . = x     # = #x      / = /x      n = Rn
  14.       A = A     B = AB      C = C       D = DPTR
  15.       i = @Ri   @ = @DPTR   > = @A+DPTR $ = @A+PC
  16.    Y: (x)  L = Long Code Address
  17.            P = Paged Code Address
  18.            R = Relative Code Address
  19.            D = Direct Register Address
  20.       (x/) B = Bit Address
  21.       (@)  w = Word
  22.            b = Byte
  23.       (i)  i = Register Pointer R0/R1
  24.       (n)  n = Register R0/R1/R2/R3/R4/R5/R6/R7
  25.            x = Reverse Order of Next 2 Operands.
  26.   */
  27.  
  28. Mode ModeTab[] = {
  29. /* acall */ { 0x11, ".",   "P" },
  30. /* add */   { 0x24, "A#",  "b" },  { 0x26, "Ai",  "i" }, { 0x25, "A.",  "D" },
  31.             { 0x28, "An",  "n" },
  32. /* addc */  { 0x34, "A#",  "b" },  { 0x36, "Ai",  "i" }, { 0x35, "A.",  "D" },
  33.             { 0x38, "An",  "n" },
  34. /* ajmp */  { 0x01, ".",   "P" },
  35. /* anl */   { 0x54, "A#",  "b" },  { 0x56, "Ai",  "i" }, { 0x55, "A.",  "D" },
  36.             { 0x58, "An",  "n" },  { 0xb0, "C/",  "B" }, { 0x82, "C.",  "B" },
  37.             { 0x53, ".#",  "Db" }, { 0x52, ".A",  "D" },
  38. /* cjne */  { 0xb6, "i#.", "ibR" },{ 0xb4, "A#.", "bR" },{ 0xb5, "A..", "DR" },
  39.             { 0xb8, "n#.", "nbR" },
  40. /* clr */   { 0xe4, "A",   "" },   { 0xc2, ".",   "B" }, { 0xc3, "C",   "" },
  41. /* cpl */   { 0xf4, "A",   "" },   { 0xb2, ".",   "B" }, { 0xb3, "C",   "" },
  42. /* da */    { 0xd4, "A",   "" },
  43. /* dec */   { 0x16, "i",   "i" },  { 0x14, "A",   ""},   { 0x15, ".",   "D" },
  44.             { 0x18, "n",   "n" },
  45. /* div */   { 0x84, "B",   "" },
  46. /* djnz */  { 0xd5, "..",  "DR" }, { 0xd8, "n.",  "nR" },
  47. /* inc */   { 0x06, "i",   "i" },  { 0x04, "A",   "" },  { 0x05, ".",   "D" },
  48.             { 0xa3, "D",   "" },   { 0x08, "n",   "n" },
  49. /* jb */    { 0x20, "..",  "BR" },
  50. /* jbc */   { 0x10, "..",  "BR" },
  51. /* jc */    { 0x40, ".",   "R" },
  52. /* jmp */   { 0x73, ">",   "" },
  53. /* jnb */   { 0x30, "..",  "BR" },
  54. /* jnc */   { 0x50, ".",   "R" },
  55. /* jnz */   { 0x70, ".",   "R" },
  56. /* jz */    { 0x60, ".",   "R" },
  57. /* lcall */ { 0x12, ".",   "L" },
  58. /* ljmp */  { 0x02, ".",   "L" },
  59. /* mov */   { 0x76, "i#",  "ib" }, { 0xf6, "iA",  "i" }, { 0xa6, "i.",  "iD" },
  60.             { 0x74, "A#",  "b" },  { 0xe6, "Ai",  "i" }, { 0xe5, "A.",  "D" },
  61.             { 0xe8, "An",  "n" },  { 0x92, ".C",  "B" }, { 0xa2, "C.",  "B" },
  62.             { 0x75, ".#",  "Db" }, { 0x86, ".i",  "iD" },{ 0xf5, ".A",  "D" },
  63.             { 0x85, "..",  "xDD" },{ 0x88, ".n",  "nD" },{ 0x90, "D#",  "w" },
  64.             { 0x78, "n#",  "nb" }, { 0xf8, "nA",  "n" }, { 0xa8, "n.",  "nD" },
  65. /* movc */  { 0x93, "A>",  "" },   { 0x83, "A$",  "" },
  66. /* movx */  { 0xf0, "@A",  "" },   { 0xf2, "iA",  "i" }, { 0xe0, "A@",  "" },
  67.             { 0xe2, "Ai",  "i" },
  68. /* mul */   { 0xa4, "B",   "" },
  69. /* nop */   { 0x00, "",    "" },
  70. /* orl */   { 0x44, "A#",  "b" },  { 0x46, "Ai",  "i" }, { 0x45, "A.",  "D" },
  71.             { 0x48, "An",  "n" },  { 0xa0, "C/",  "B" }, { 0x72, "C.",  "B" },
  72.             { 0x43, ".#",  "Db" }, { 0x42, ".A",  "D" },
  73. /* pop */   { 0xd0, ".",   "D" },
  74. /* push */  { 0xc0, ".",   "D" },
  75. /* ret */   { 0x22, "",    "" },
  76. /* reti */  { 0x32, "",    "" },
  77. /* rl */    { 0x23, "A",   "" },
  78. /* rlc */   { 0x33, "A",   "" },
  79. /* rr */    { 0x03, "A",   "" },
  80. /* rrc */   { 0x13, "A",   "" },
  81. /* setb */  { 0xd2, ".",   "B" },  { 0xd3, "C",   "" },
  82. /* sjmp */  { 0x80, ".",   "R" },
  83. /* subb */  { 0x94, "A#",  "b" },  { 0x96, "Ai",  "i" }, { 0x95, "A.",  "D" },
  84.             { 0x98, "An",  "n" },
  85. /* swap */  { 0xc4, "A",   "" },
  86. /* xch */   { 0xc6, "Ai",  "i" },  { 0xc5, "A.",  "D" }, { 0xc8, "An",  "n" },
  87. /* xchd */  { 0xd6, "Ai",  "i" },
  88. /* xrl */   { 0x64, "A#",  "b" },  { 0x66, "Ai",  "i" }, { 0x65, "A.",  "D" },
  89.             { 0x68, "An",  "n" },  { 0x63, ".#",  "Db" },{ 0x62, ".A",  "D" }
  90. };
  91.  
  92. Code CodeTab[] = {
  93.    { "acall", 1 }, { "add",   4 }, { "addc",  4 }, { "ajmp",  1 },
  94.    { "anl",   8 }, { "cjne",  4 }, { "clr",   3 }, { "cpl",   3 },
  95.    { "da",    1 }, { "dec",   4 }, { "div",   1 }, { "djnz",  2 },
  96.    { "inc",   5 }, { "jb",    1 }, { "jbc",   1 }, { "jc",    1 },
  97.    { "jmp",   1 }, { "jnb",   1 }, { "jnc",   1 }, { "jnz",   1 },
  98.    { "jz",    1 }, { "lcall", 1 }, { "ljmp",  1 }, { "mov",  18 },
  99.    { "movc",  2 }, { "movx",  4 }, { "mul",   1 }, { "nop",   1 },
  100.    { "orl",   8 }, { "pop",   1 }, { "push",  1 }, { "ret",   1 },
  101.    { "reti",  1 }, { "rl",    1 }, { "rlc",   1 }, { "rr",    1 },
  102.    { "rrc",   1 }, { "setb",  2 }, { "sjmp",  1 }, { "subb",  4 },
  103.    { "swap",  1 }, { "xch",   3 }, { "xchd",  1 }, { "xrl",   6 },
  104.    { 0, 0 }
  105. };
  106.  
  107. /* Argument buffer. */
  108. #define A_MAX 4
  109. char XBuf[A_MAX + 1]; Exp XExp[A_MAX];
  110.  
  111. void OpInit(void) {
  112.    Code *OC; Mode *M; /*int I, J;*/
  113.    for (OC = CodeTab, M = ModeTab; OC < CodeTab + ELEMENTS(CodeTab); OC++) {
  114.       OC->Start = M; M += OC->Modes;
  115.       if (M > ModeTab + ELEMENTS(ModeTab))
  116.          fprintf(stderr, "Bad opcode initialization.\n"), exit(1);
  117.    }
  118. }
  119.  
  120. void ParseArgs(byte Mnem) {
  121.    Lexical L = OldL; Code *CP; Mode *MP; int XReg;
  122.    char *XP, *S; Exp *EP, E; byte Op; /* word W;*/
  123.    XP = XBuf, EP = XExp;
  124.    do {
  125.       L = Scan();
  126.       if (L == SEMI) {
  127.          if (XP > XBuf) ERROR("Extra ','."); break;
  128.       }
  129.       switch (L) {
  130.          case POUND: *XP = '#', Scan(), *EP++ = Parse(2); break;
  131.          case DIV: *XP = '/', Scan(), *EP++ = Parse(2); break;
  132.          case AT:
  133.             L = Scan();
  134.             switch (L) {
  135.                case REGISTER: switch ((Register)Value) {
  136.                   case ACC:
  137.                      if (Scan() != PLUS)
  138.                         ERROR("Cannot use @A."), *XP = ' ';
  139.                      else if (Scan() != REGISTER)
  140.                         ERROR("Missing DPTR or PC after @A+"), *XP = ' ';
  141.                      else {
  142.                         switch (Value) {
  143.                            case ACC:ERROR("Cannot use @A+A"), *XP = ' '; break;
  144.                            case AB:ERROR("Cannot use @A+AB."); *XP = ' '; break;
  145.                            case CY:ERROR("Cannot use @A+C."); *XP = ' '; break;
  146.                            case DPTR: *XP = '>'; break;
  147.                            case PC: *XP = '$'; break;
  148.                            default:ERROR("Cannot use @A+Rn"); *XP = ' '; break;
  149.                         }
  150.                         Scan();
  151.                      }
  152.                   break;
  153.                   case AB: ERROR("Cannot use @AB."); *XP = ' '; break;
  154.                   case CY: ERROR("Cannot use @C."); *XP = ' '; break;
  155.                   case DPTR: *XP = '@'; Scan(); break;
  156.                   case PC: ERROR("Cannot use @PC."); *XP = ' '; break;
  157.                   default:
  158.                      Value -= (short)R0;
  159.                      if (Value != 0 && Value != 1) {
  160.                         ERROR("Register in @Rn out of range."); *XP = ' ';
  161.                      } else *XP = 'i', XReg = Value;
  162.                      Scan();
  163.                   break;
  164.                }
  165.                break;
  166.                default:
  167.                   ERROR("Register must appear after @."); *XP = ' ';
  168.                break;
  169.             }
  170.          break;
  171.          case REGISTER: switch ((Register)Value) {
  172.             case ACC: *XP = 'A'; break;
  173.             case AB: *XP = 'B'; break;
  174.             case CY: *XP = 'C'; break;
  175.             case DPTR: *XP = 'D'; break;
  176.             case PC:
  177.                ERROR("Cannot use PC as a register.");
  178.                *XP = '.', *EP++ = MakeExp(AddrX, SegP, (word)LOC);
  179.             break;
  180.             default: *XP = 'n', XReg = Value - (short)R0; break;
  181.          }
  182.             Scan();
  183.          break;
  184.          default: *XP = '.', *EP++ = Parse(2); break;
  185.       }
  186.       L = OldL;
  187.       if (XP++ >= XBuf + A_MAX) {
  188.          ERROR("Too many arguments specified."); return;
  189.          while (L != SEMI && L != 0) L = Scan();
  190.          break;
  191.       }
  192.    } while (L == COMMA);
  193.    if (!Active) return;
  194.    *XP = 0, *EP = 0;
  195.    CP = CodeTab + Mnem;
  196.    for (MP = CP->Start; MP < CP->Start + CP->Modes; MP++)
  197.       if (strcmp(XBuf, MP->X) == 0) break;
  198.    if (MP >= CP->Start + CP->Modes) {
  199.       ERROR("Invalid addressing mode: %s.", CP->Name); return;
  200.    }
  201.    Op = MP->OpCode;
  202.    S = MP->Y, EP = XExp;
  203.    switch (*S) {
  204.       case 'n': S++; Op |= XReg&7; break;/* Register R0/R1/R2/R3/R4/R5/R6/R7 */
  205.       case 'i': S++; Op |= XReg&1; break;/* Register Pointer @R0/@R1 */
  206.       case 'x': E = EP[0], EP[0] = EP[1], EP[1] = E; S++; break;
  207.       case 'P': Reloc(Op, 'P', *EP++); return; /* P Paged Address */
  208.    }
  209.    PByte(Op);
  210.    for (; *S != 0; S++) Reloc(0, *S, *EP++);
  211. }
  212.